package org.xlp.encryption;

import org.xlp.utils.XLPCharsetUtil;
import org.xlp.utils.XLPStringUtil;

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

/**
 * Description: MD5或SHA加密
 * <br/>date: 2024/12/6 23:51
 *
 * @version 1.0
 * @author: xlp
 */
public class MD5HashEncryption {
    public enum HashType {
        MD5("MD5"),
        SHA256("SHA-256"),
        SHA1("SHA-1"),
        SHA224("SHA-224"),
        SHA384("SHA-384"),
        SHA512("SHA-512");

        private String name;

        private HashType(String name){
            this.name = name;
        }

        public String getName() {
            return name;
        }
    }

    /**
     * 加密方式
     */
    private HashType hashType = HashType.MD5;

    /**
     * 加密额外填充值
     */
    private String extraValue = "";

    /**
     * 字符编码名称，把字符串转换成字节数字时使用
     */
    private String charsetName = XLPCharsetUtil.UTF8;

    public MD5HashEncryption(){}

    /**
     * 构造函数
     * @param hashType 加密方式
     */
    public MD5HashEncryption(HashType hashType){
        setHashType(hashType);
    }

    public HashType getHashType() {
        return hashType;
    }

    public void setHashType(HashType hashType) {
        if (hashType != null) this.hashType = hashType;
    }

    public String getExtraValue() {
        return extraValue;
    }

    public void setExtraValue(String extraValue) {
        this.extraValue = extraValue;
    }

    public String getCharsetName() {
        return charsetName;
    }

    public void setCharsetName(String charsetName) {
        if (!XLPStringUtil.isEmpty(charsetName)){
            this.charsetName = charsetName;
        }
    }

    /**
     * MD5或SHA加密
     *
     * @param origin
     *            原始字符串
     * @return 返回加密后的字符串
     * @throws EncryptException 假如加密失败，则抛出该异常
     * @throws NullPointerException 或假如参数为null，则抛出该异常
     */
    public String encode(String origin) throws EncryptException{
        if (origin == null){
            throw new NullPointerException("origin parameter must not be null！");
        }
        try {
            // 加密
            MessageDigest md = MessageDigest.getInstance(hashType.getName());
            md.update((extraValue + "." + origin).getBytes(charsetName));
            return bytesToHexString(md.digest());
        } catch (NoSuchAlgorithmException | UnsupportedEncodingException e) {
            throw new EncryptException(e);
        }
    }

    /**
     * byte数组转换成16进制字符串
     *
     * @param bytes
     * @return
     */
    private String bytesToHexString(byte[] bytes) {
        StringBuilder stringBuilder = new StringBuilder();
        if (bytes == null || bytes.length <= 0) {
            return null;
        }
        for (byte aByte : bytes) {
            int v = aByte & 0xFF;
            String hv = Integer.toHexString(v);
            if (hv.length() < 2) {
                stringBuilder.append(0);
            }
            stringBuilder.append(hv);
        }
        return stringBuilder.toString();
    }
}
